package com.informatics.polymer.server.DescriptorCalculation;

import java.util.HashMap;
import org.openscience.cdk.DefaultChemObjectBuilder;
import org.openscience.cdk.exception.CDKException;
import org.openscience.cdk.interfaces.IMolecule;
import org.openscience.cdk.qsar.DescriptorValue;
import org.openscience.cdk.qsar.IMolecularDescriptor;
//import org.openscience.cdk.qsar.descriptors.molecular.ALOGPDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.ALOGPDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.APolDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.AromaticAtomsCountDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.AromaticBondsCountDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.AtomCountDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.BondCountDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.FragmentComplexityDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.HBondAcceptorCountDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.HBondDonorCountDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.KappaShapeIndicesDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.RuleOfFiveDescriptor;
import org.openscience.cdk.qsar.descriptors.molecular.TPSADescriptor;
import org.openscience.cdk.qsar.result.IDescriptorResult;
import org.openscience.cdk.smiles.SmilesParser;


/**
 * A class to calculate Chemistry Development Kit (CDK) descriptors for
 * newly added repeat units.
 * @author ed
 * @version 1.0
 */
public class MolecularDescriptorCalculation {
	/**
	 * Instantiates a MolecularDescriptorCalculation object.
	 */
	public MolecularDescriptorCalculation(){
	}
	/**
	 * Method to calculate descriptors for a repeat unit.
	 * @param - smileString, the molecule representation to have descriptors generated.
	 * @return HashMap of calculated descriptor values.
	 * @throws CDKException 
	 */
	public HashMap<String,Double> calculateAllDescriptors(final String smileString) throws CDKException{
		SmilesParser sp = new SmilesParser(DefaultChemObjectBuilder.getInstance());
		IMolecule m = sp.parseSmiles(smileString);
		IMolecularDescriptor aLOGPDescriptor = new ALOGPDescriptor();
		DescriptorValue vals = aLOGPDescriptor.calculate(m);
		String [] calculatedDescriptors = vals.getValue().toString().split(",");
		HashMap<String,Double> descriptorValues = new HashMap<String,Double>();
		int counter = 0;
		for(String s: calculatedDescriptors){
			Double data = Double.parseDouble(s);
			if (counter == 0){
				descriptorValues.put("ALOGP",data);	
			}
			else if(counter == 1){
				descriptorValues.put("ALogP2", data);
			}
			else if(counter == 2){
				descriptorValues.put("AMR",data);
			}
			counter++;
		}
		//APolDescriptor
		IMolecularDescriptor aPol = new APolDescriptor();
		IDescriptorResult aPolValue = aPol.calculate(m).getValue();
		descriptorValues.put("APol", Double.parseDouble(aPolValue.toString()));
		//Aromatic atom count
		IMolecularDescriptor aromaticAtomCount = new AromaticAtomsCountDescriptor();
		IDescriptorResult aromaticAtomCountValue = aromaticAtomCount.calculate(m).getValue();
		descriptorValues.put("AromaticAtomCount",Double.parseDouble(aromaticAtomCountValue.toString()));
		//Aromatic bond count
		IMolecularDescriptor aromaticBondCount = new AromaticBondsCountDescriptor();
		descriptorValues.put("AromaticBondCount",Double.parseDouble(aromaticBondCount.calculate(m).getValue().toString()));
		//Atom count
		IMolecularDescriptor atomCount = new AtomCountDescriptor();
		descriptorValues.put("AtomCount", Double.parseDouble(atomCount.calculate(m).getValue().toString()));
		//Bond count descriptor
		IMolecularDescriptor bondCount = new BondCountDescriptor();
		descriptorValues.put("BondCount", Double.parseDouble(bondCount.calculate(m).getValue().toString()));
		//Fragment complexity descriptor
		IMolecularDescriptor fragmentComplexityDescriptor = new FragmentComplexityDescriptor();
		descriptorValues.put("FragmentComplexity", Double.parseDouble(fragmentComplexityDescriptor.calculate(m).getValue().toString()));
		//H-bond Acceptor count
		IMolecularDescriptor hBondAcceptorCount = new HBondAcceptorCountDescriptor();
		descriptorValues.put("HBACount", Double.parseDouble(hBondAcceptorCount.calculate(m).getValue().toString()));
		//H-bond Donor count
		IMolecularDescriptor hBondDonorCount = new HBondDonorCountDescriptor();
		descriptorValues.put("HBDCount", Double.parseDouble(hBondDonorCount.calculate(m).getValue().toString()));
		//Kappa shape descriptor
		IMolecularDescriptor kappaShapes = new KappaShapeIndicesDescriptor();
		String [] separateKappaIndices = kappaShapes.calculate(m).getValue().toString().split(",");
		descriptorValues.put("Kappa1", Double.parseDouble(separateKappaIndices[0]));
		descriptorValues.put("Kappa2", Double.parseDouble(separateKappaIndices[1]));
		descriptorValues.put("Kappa3", Double.parseDouble(separateKappaIndices[2]));
		//Lipinski Rule of 5 descriptor
		IMolecularDescriptor ruleOfFive = new RuleOfFiveDescriptor();
		descriptorValues.put("RuleOf5", Double.parseDouble(ruleOfFive.calculate(m).getValue().toString()));
		//TPSA
		IMolecularDescriptor tPSA = new TPSADescriptor();
		descriptorValues.put("TPSA", Double.parseDouble(tPSA.calculate(m).getValue().toString()));
		return descriptorValues;
	}
/*	public static void main(String[]args) throws CDKException, IOException{
		MolecularDescriptorCalculation ma = new MolecularDescriptorCalculation();
		//HashMap<String,Double> descriptors = ma.calculateAllDescriptors("[*]O[Si](C)(C)[*]");
		String theZipfile = "/home/ed/Desktop/Miscellaneous/SmileRUs.zip";
		ZipFile zipFile = new ZipFile(theZipfile);
		Enumeration<? extends ZipEntry> entries = zipFile.entries();
		BufferedWriter bw = new BufferedWriter(new FileWriter("/home/ed/RUWithDescriptors.txt"));
		while(entries.hasMoreElements()){
			ZipEntry entry = (ZipEntry)entries.nextElement();
			if(entry.toString().contains(".pml.xml")){
				InputStream in = zipFile.getInputStream(entry);
				BufferedReader br = new BufferedReader(new InputStreamReader(in));
				String [] repeatUnitInfo = br.readLine().split("\t");
				String [] name = entry.getName().split(".pml");
				String [] repeatUnitName = name[0].split("/");
				HashMap<String,Double> descriptors = ma.calculateAllDescriptors(repeatUnitInfo[0]);
				bw.write(repeatUnitName[1]+","+repeatUnitInfo[0]+","+Double.toString(descriptors.get("ALOGP"))+","+Double.toString(descriptors.get("ALogP2"))+","+Double.toString(descriptors.get("AMR"))+","+Double.toString(descriptors.get("APol"))+","+Double.toString(descriptors.get("AromaticAtomCount"))+","
				+Double.toString(descriptors.get("AromaticBondCount"))+","+Double.toString(descriptors.get("AtomCount"))+","+Double.toString(descriptors.get("BondCount"))+","+
				Double.toString(descriptors.get("FragmentComplexity"))+","+Double.toString(descriptors.get("HBACount"))+","+Double.toString(descriptors.get("HBDCount"))+","+
				Double.toString(descriptors.get("Kappa1"))+","+Double.toString(descriptors.get("Kappa2"))+","+Double.toString(descriptors.get("Kappa3"))+","+Double.toString(descriptors.get("RuleOf5"))+","
				+Double.toString(descriptors.get("TPSA"))+"\n");
				//Double.toString(descriptors.get("ALOGP"))+","+Double.toString(descriptors.get("ALogP2"))+","+Double.toString(descriptors.get("AMR"))+
			}
		}
	}*/
}
